#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
#define endl '\n'
const int N = 105;

int n, m;
int a[N];
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
struct Edge {
  int v, x, y;
};
vector<Edge> ch[N];
vector<int> path;
bool dfs2(int u, int val) {
  path.push_back(u);
  a[u] = val;
  for (auto p : ch[u]) {
    int v = p.v, x = p.x, y = p.y;
    if (a[u] % x) return false;
    if (y % a[u]) return false;
    if (a[v]) {
      if (a[v] != y / a[u] * x || gcd(a[u], a[v]) != x) {
        return false;
      }
    } else {
      if (!dfs2(v, y / a[u] * x)) {
        return false;
      }
    }
  }
  return true;
}

bool dfs(int u) {
  if (ch[u].empty()) {
    a[u] = 1;
    return true;
  }
  int x = ch[u][0].x, y = ch[u][0].y;
  int k = y / x;
  for (int i = 1; i * i <= k; i++) {
    if (k % i) continue;
    int j = k / i;
    if (gcd(i, j) != 1) continue;
    path.clear();
    if (dfs2(u, x * i)) return true;
    for (int v : path) a[v] = 0;
    if (j != i) {
      path.clear();
      if (dfs2(u, x * j)) return true;
      for (int v : path) a[v] = 0;
    }
  }
  return false;
}
void solve() {
  cin >> n >> m;
  rep(i, 1, m) {
    int u, v, x, y;
    cin >> u >> v >> x >> y;
    if (y % x) {
      cout << "NO";
      return;
    }
    ch[u].push_back({v, x, y});
    ch[v].push_back({u, x, y});
  }
  rep(i, 1, n) {
    if (!a[i] && !dfs(i)) {
      cout << "NO";
      return;
    }
  }
  cout << "YES" << endl;
  rep(i, 1, n) cout << a[i] << ' ';
  return;
}
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int t = 1;
  while (t--) solve();
  return 0;
}